package pulpfizz.physics;

import org.jbox2d.collision.Shape;
import org.jbox2d.collision.ShapeDef;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import pulpcore.math.CoreMath;

import java.util.ArrayList;
import java.util.List;

public class Material
{
    static List<Material> materials = new ArrayList<Material>();
    static {
        materials.add(WOOD());
        materials.add(METAL());
        materials.add(STONE());
        materials.add(PLASTIC());
//        materials.add(STYROFOAM());
        materials.add(RUBBER());
        materials.add(ICE());
        materials.add(DEAD_WEIGHT());
        materials.add(BOUNCY_WEIGHT());
    }
    public static Material RANDOM() {
        return materials.get(CoreMath.rand(0,materials.size()-1));
    }
    public static Material WOOD()
	{
		Material m = new Material();
		m.setDensity(woodD);
		m.setRestitution(woodR);
		m.setFriction(woodF);
		return m;
	}

	public static Material METAL()
	{
		Material m = new Material();
		m.setDensity(woodD * 10);
		m.setRestitution(woodR * 1f);
		m.setFriction(woodF * .25f);
		return m;
	}

	public static Material STONE()
	{
		Material m = new Material();
		m.setDensity(woodD * 10);
		m.setRestitution(woodR * 0.3f);
		m.setFriction(woodF * 1.5f);
		return m;
	}

	public static Material PLASTIC()
	{
		Material m = new Material();
		m.setDensity(woodD * .5f);
		m.setRestitution(woodR * .5f);
		m.setFriction(woodF * .75f);
		return m;
	}

	public static Material STYROFOAM()
	{
		Material m = new Material();
		m.setDensity(woodD * .02f);
		m.setRestitution(woodR * 1f);
		m.setFriction(woodF);
		m.setLinearDamping(0.3f);
		m.setAngularDamping(0.4f);
		return m;
	}

	public static Material RUBBER()
	{
		Material m = new Material();
		m.setDensity(woodD * .75f);
		m.setRestitution(0.95f);
		m.setFriction(woodF * 1.5f);
		return m;
	}

	public static Material ICE()
	{
		Material m = new Material();
		m.setRestitution(0f);
		m.setFriction(0.0f);
		return m;
	}

	public static Material DEAD_WEIGHT()
	{
		Material m = new Material();
		m.setRestitution(0);
		m.setFriction(1f);
		m.setDensity(woodD * 10);
		return m;
	};
    public static Material BOUNCY_WEIGHT()
    {
        Material m = new Material();
        m.setRestitution(0.95f);
        m.setFriction(1f);
        m.setDensity(woodD * 10);
        return m;
    };

	private float friction = 0.4f;
	private float restitution = 0.2f;
	private float density = 1f;
	private float linearDamping = 0f;
	private float angularDamping = 0f;

	public static final float woodD = 1f;
	public static final float woodR = 0.17f;
	public static final float woodF = 0.5f;

    public Material(float friction, float restitution, float density, float linearDamping, float angularDamping) {
        this.setFriction(woodF * friction);
        this.setRestitution(woodR * restitution);
        this.setDensity(woodD * density);
        this.setLinearDamping(linearDamping);
        this.setAngularDamping(angularDamping);
        init();
    }
    public Material()
	{
		init();
	}

	void init()
	{

	}

	/**
	 * Applies this material to the body and all of its enclosed shapes.
	 * @param b
	 */
	public void applyAll(Body b)
	{
		apply(b);
		Shape s = b.m_shapeList;
		while (s != null)
		{
			apply(s);
			s = s.m_next;
		}
		b.setMassFromShapes();
	}

    public void apply(Body b) {
        b.m_angularDamping = getAngularDamping();
        b.m_linearDamping = getLinearDamping();
    }

    public void apply(BodyDef bd) {
        bd.angularDamping = getAngularDamping();
        bd.linearDamping = getLinearDamping();
    }

    public void apply(Shape s)
	{
		s.m_friction = getFriction();
		s.m_restitution = getRestitution();
		s.m_density = getDensity();
	}

	public void apply(ShapeDef sd)
	{
		sd.friction = getFriction();
		sd.restitution = getRestitution();
		sd.density = getDensity();
	}

	/*
	 * Getters and setters.
	 */

	public float getFriction()
	{
		return friction;
	}

	public void setFriction(float friction)
	{
		this.friction = friction;
	}

	public float getRestitution()
	{
		return restitution;
	}

	public void setRestitution(float restitution)
	{
		this.restitution = restitution;
	}

	public float getDensity()
	{
		return density;
	}

	public void setDensity(float density)
	{
		this.density = density;
	}

	public float getLinearDamping()
	{
		return linearDamping;
	}

	public void setLinearDamping(float linearDamping)
	{
		this.linearDamping = linearDamping;
	}

	public float getAngularDamping()
	{
		return angularDamping;
	}

	public void setAngularDamping(float angularDamping)
	{
		this.angularDamping = angularDamping;
	}

}
